﻿namespace Mp3Observer.Common.StateManagement
{
    #region usings

    using System.Windows;
    using System.Windows.Input;
    using Microsoft.Expression.Interactivity.Core;
    using Mp3Observer.Common.Commands;

    #endregion

    /// <summary>
    /// Custom GoToState Action needed that MVVM and VSM work together.
    /// </summary>
    public class VisualStateManagerInvoker : GoToStateAction
    {
        /// <summary>
        /// CurrentState Attached Dependency Property
        /// </summary>
        public static readonly DependencyProperty CurrentStateProperty =
            DependencyProperty.RegisterAttached("CurrentState", typeof(string), typeof(VisualStateManagerInvoker),
            new PropertyMetadata((string)null, new PropertyChangedCallback(OnCurrentStateChanged)));

        /// <summary>
        /// GoToStateAction Attached Dependency Property
        /// </summary>
        public static readonly DependencyProperty GoToStateActionProperty =
            DependencyProperty.RegisterAttached("GoToStateAction", typeof(ICommand), typeof(VisualStateManagerInvoker),
            new PropertyMetadata((ICommand)null));

        /// <summary>
        /// ShouldUseTransition Attached Dependency Property
        /// </summary>
        public static readonly DependencyProperty ShouldUseTransitionProperty =
            DependencyProperty.RegisterAttached("ShouldUseTransition", typeof(bool), typeof(VisualStateManagerInvoker),
            new PropertyMetadata(true));

        /// <summary>
        /// Gets the CurrentState property.  This dependency property indicates ....
        /// </summary>
        /// <param name="dependencyObject">The dependency object.</param>
        /// <returns>the CurrentState</returns>
        public static string GetCurrentState(DependencyObject dependencyObject)
        {
            return (string)dependencyObject.GetValue(CurrentStateProperty);
        }

        /// <summary>
        /// Sets the CurrentState property.  This dependency property indicates ....
        /// </summary>
        /// <param name="dependencyObject">The dependency object.</param>
        /// <param name="value">The value.</param>
        public static void SetCurrentState(DependencyObject dependencyObject, string value)
        {
            dependencyObject.SetValue(CurrentStateProperty, value);
        }

        /// <summary>
        /// Gets the GoToStateAction property.  This dependency property indicates ....
        /// </summary>
        /// <param name="dependencyObject">The dependency object.</param>
        /// <returns>the ICommand</returns>
        public static ICommand GetGoToStateAction(DependencyObject dependencyObject)
        {
            return (ICommand)dependencyObject.GetValue(GoToStateActionProperty);
        }

        /// <summary>
        /// Sets the GoToStateAction property.  This dependency property indicates ....
        /// </summary>
        /// <param name="dependencyObject">The dependency object.</param>
        /// <param name="value">The value.</param>
        public static void SetGoToStateAction(DependencyObject dependencyObject, ICommand value)
        {
            dependencyObject.SetValue(GoToStateActionProperty, value);
        }

        /// <summary>
        /// Gets the ShouldUseTransition property.  This dependency property indicates ....
        /// </summary>
        /// <param name="dependencyObject">The dependency object.</param>
        /// <returns>the ShouldUseTransition</returns>
        public static bool GetShouldUseTransition(DependencyObject dependencyObject)
        {
            return (bool)dependencyObject.GetValue(ShouldUseTransitionProperty);
        }

        /// <summary>
        /// Sets the ShouldUseTransition property.  This dependency property indicates ....
        /// </summary>
        /// <param name="dependencyObject">The dependency object.</param>
        /// <param name="value">if set to <c>true</c> [value].</param>
        public static void SetShouldUseTransition(DependencyObject dependencyObject, bool value)
        {
            dependencyObject.SetValue(ShouldUseTransitionProperty, value);
        }

        /// <summary>
        /// Handles changes to the CurrentState property.
        /// </summary>
        /// <param name="dependencyObject">The dependency object.</param>
        /// <param name="e">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
        private static void OnCurrentStateChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            if (GetGoToStateAction(dependencyObject) == null)
            {
                var command = new RelayCommand<object>(x =>
                {
                    var stateAction = new VisualStateManagerInvoker();
                    stateAction.Attach(dependencyObject);
                    stateAction.UseTransitions = GetShouldUseTransition(dependencyObject);
                    stateAction.StateName = (string)x;
                    stateAction.Invoke(null);
                });
                SetGoToStateAction(dependencyObject, command);
            }
        }
    }
}
